#region Using Directives

using System;
using System.Collections.Generic;
using System.IO;
using System.Globalization;
using Microsoft.Practices.ComponentModel;
using Microsoft.Practices.RecipeFramework;
using Microsoft.Practices.RecipeFramework.Services;

using EnvDTE;
using EnvDTE80;

#endregion

namespace EEst.SoftwareFactory.Actions
{
    class ImportContents2Action : Action
    {
        #region Input Properties

        [Input]
        public string SourcePath
        {
            get { return sourcePath; }
            set { sourcePath = value; }
        } string sourcePath;

        [Input]
        public string DestPath
        {
            get { return destPath; }
            set { destPath = value; }
        } string destPath;

        [Input]
        public string TargetName
        {
            get { return targetName; }
            set { targetName = value; }
        } string targetName;

        [Input]
        public string VSVersion
        {
            get { return vsVersion; }
            set { vsVersion = value; }
        } string vsVersion;

        [Input]
        public string CygwinHome
        {
            get { return cygwinHome; }
            set { cygwinHome = value; }
        } string cygwinHome;

        [Input]
        public string BrickOSHome
        {
            get { return brickOSHome; }
            set { brickOSHome = value; }
        } string brickOSHome;

        [Input]
        public string H8ToolsHome
        {
            get { return h8ToolsHome; }
            set { h8ToolsHome = value; }
        } string h8ToolsHome;
        #endregion

        #region Output Properties

        [Output]
        public string ProjectFileName
        {
            get { return projectFileName; }
            set { projectFileName = value; }
        } string projectFileName;

        #endregion

        #region IAction Members

        private List<string> copiedFils = new List<string>();
        private List<string> madeDirs = new List<string>();
        private Dictionary<string, string> configWords = new Dictionary<string, string>();

        public override void Execute()
        {
            GuidancePackage gp = (GuidancePackage)GetService(typeof(IExecutionService));
            DTE vs = GetService<DTE>(true);
            Solution2 currentSolution = vs.Solution as Solution2;
            string gpBasePath = gp.BasePath;

            configWords.Add("CygwinHome", CygwinHome);
            configWords.Add("BrickOSHome", BrickOSHome);
            configWords.Add("H8ToolsHome", h8ToolsHome);

            string srcAbstPath = String.Format(CultureInfo.InvariantCulture, @"{0}\{1}\{2}", gpBasePath, sourcePath, targetName);
            if (Directory.Exists(srcAbstPath))
            {
                string solutionFile = (string)currentSolution.Properties.Item("Path").Value;
                string solutionPath = Path.GetDirectoryName(solutionFile);
                string dstAbstPath = String.Format(CultureInfo.InvariantCulture, @"{0}\{1}", solutionPath, destPath);
                if (Directory.Exists(dstAbstPath))
                {
                    CopyContents(srcAbstPath, dstAbstPath, targetName);
                }
            }
        }

        private void CopyContents(string srcPath, string dstPath, string targetName)
        {
            string tgtAbstPath = String.Format(CultureInfo.InvariantCulture, @"{0}\{1}", dstPath, targetName);
            if (!Directory.Exists(tgtAbstPath))
            {
                DirectoryInfo dstDi= Directory.CreateDirectory(tgtAbstPath);
                madeDirs.Add(dstDi.FullName);
                string[] files = Directory.GetFiles(srcPath);
                for (int i = 0; i < files.Length; i++)
                {
                    FileInfo fi = new FileInfo(files[i]);
                    string tmp = fi.FullName;
                    string dstFileName = String.Format(CultureInfo.InvariantCulture, @"{0}\{1}", tgtAbstPath, fi.Name);
                    copiedFils.Add(dstFileName);
                    if (dstFileName.EndsWith(".vcproj")) {
                        projectFileName = dstFileName;
                        Dictionary<string, string> xwords = new Dictionary<string, string>();
                        xwords.Add("VSVersion", VSVersion);
                        CopyAndTranslateFile(fi.FullName, dstFileName, xwords);
                    }
                    else if (dstFileName.EndsWith("Makefile.xc"))
                    {
                        CopyAndTranslateFile(fi.FullName, dstFileName, configWords);
                    }
                    else if (dstFileName.EndsWith("XCConfig.xml"))
                    {
                        CopyAndTranslateFile(fi.FullName, dstFileName, configWords);
                    }
                    else
                    {
                        fi.CopyTo(dstFileName);
                    }
                }
                string[] dirs = Directory.GetDirectories(srcPath);
                for (int i = 0; i < dirs.Length; i++)
                {
                    DirectoryInfo di = new DirectoryInfo(dirs[i]);
                    CopyContents(dirs[i], dstDi.FullName, di.Name);
                }
            }

        }
        private void CopyAndTranslateFile(string srcFile, string dstFile, Dictionary<string, string> xwords)
        {
            using (TextReader reader = new StreamReader(srcFile))
            {
                using (TextWriter writer = new StreamWriter(new FileStream(dstFile, FileMode.Create, FileAccess.Write)))
                {
                    string line = reader.ReadLine();
                    while (line != null)
                    {
                        foreach (KeyValuePair<string, string> kvp in xwords)
                        {
                            string candidate = "$" + kvp.Key + "$";
                            line = line.Replace(candidate, kvp.Value);
                        }
                        writer.WriteLine(line);
                        line = reader.ReadLine();
                    }
                    writer.Flush();
                    writer.Close();
                }
            }
        }

        public override void Undo()
        {
            foreach (string file in copiedFils)
            {
                FileInfo fi = new FileInfo(file);
                fi.Delete();
            }
            copiedFils.Clear();
            madeDirs.Reverse();
            foreach (string dir in madeDirs)
            {
                DirectoryInfo di = new DirectoryInfo(dir);
                di.Delete(true);
            }
            madeDirs.Clear();
        }

        #endregion
    }
}
